package com.ruoyi.problem.service.impl;
import java.net.InetAddress;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.CertAlipayRequest;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import com.ruoyi.common.aliyun.AlipayConfig;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.CommonUtil;
import com.ruoyi.common.utils.OrderNumberGeneratorUtil;
import com.ruoyi.common.utils.aliyun.ThroughUtil;
import com.ruoyi.common.utils.date.DateUtils;
import com.ruoyi.common.wx.WxConfig;
import com.ruoyi.framework.security.auth.JWTUser;
import com.ruoyi.framework.security.auth.RequestContext;
import com.ruoyi.order.domain.OrderInfo;
import com.ruoyi.order.domain.OrderTask;
import com.ruoyi.order.mapper.OrderInfoMapper;
import com.ruoyi.order.service.IOrderTaskService;
import com.ruoyi.problem.domain.ProblemAnswer;
import com.ruoyi.problem.domain.ProblemConsult;
import com.ruoyi.problem.mapper.ProblemAnswerMapper;
import com.ruoyi.problem.mapper.ProblemConsultMapper;
import com.ruoyi.problem.pojo.AnswerDTO;
import com.ruoyi.problem.pojo.OrderGrabbingPoolDTO;
import com.ruoyi.problem.pojo.RewardVO;
import com.ruoyi.problem.service.AppProblemService;
import com.ruoyi.system.domain.SystemDivine;
import com.ruoyi.system.mapper.SystemDivineMapper;
import com.ruoyi.system.service.IPriceSettingService;
import com.ruoyi.thread.TaskAsync;
import com.ruoyi.user.domain.User;
import com.ruoyi.user.domain.UserCapitalFlow;
import com.ruoyi.user.mapper.UserMapper;
import com.ruoyi.user.service.IUserCapitalFlowService;
import com.ruoyi.user.service.IUserTotalCapitalService;

import cn.hutool.core.collection.CollectionUtil;

@Service
public class AppProlemServiceImpl implements AppProblemService {

	@Autowired
	private OrderInfoMapper orderInfoMapper;
	@Autowired
	private WxConfig wxConfig;
	@Autowired
	private AlipayConfig alipayConfig;
	@Autowired
	private ProblemConsultMapper problemConsultMapper;
	@Autowired
	private ProblemAnswerMapper problemAnswerMapper;
	@Autowired
	private SystemDivineMapper systemDivineMapper;
	@Autowired
	private UserMapper userMapper;
	@Autowired
	private IUserTotalCapitalService userTotalCapitalService;
	@Autowired
	private IUserCapitalFlowService userCapitalFlowService;
	@Autowired
	private TaskAsync taskAsync;
	@Autowired
	private IPriceSettingService priceSettingService;
	@Autowired
	private IOrderTaskService orderTaskService;
	
	/**
	 * 	获取用户ID
	 * @return
	 */
	private Long getLoginUserId() {
		Object object = RequestContext.get("userInfo");
		if(null == object) {
			return null;
		}
		JWTUser jwtUser = (JWTUser) object;
		if(null == jwtUser || null == jwtUser.getId()) {
			return null;
		}
		return jwtUser.getId();
	}
	/**
	 *  微信支付
	 * @param orderNo
	 * @param amount
	 * @param remark
	 * @param tradeType
	 * @return
	 */
	private AjaxResult createWxPayOrder(String orderNo, String amount, String remark, String tradeType) {
		try {
			WXPay wxpay = new WXPay(wxConfig);
			Map<String, String> data = new HashMap<>();
			//微信开放平台审核通过的应用APPID（请登录open.weixin.qq.com查看，注意与公众号的APPID不同）
			data.put("appid", wxConfig.getAppID());
			//微信支付分配的商户号
			data.put("mch_id", wxConfig.getMchID());
			//            data.put("mch_id", wxConfig.getMchID());
			//data.put("openid", openId);
			//随机字符串，不长于32位
			data.put("nonce_str", WXPayUtil.generateNonceStr());
			//APP——需传入应用市场上的APP名字-实际商品名称，天天爱消除-游戏充值。
			data.put("body", "必答咨询APP");
			//商户系统内部订单号，要求32个字符内，只能是数字、大小写字母_-|*且在同一个商户号下唯一
			data.put("out_trade_no", orderNo);
			//订单总金额，单位为分
			data.put("total_fee", ThroughUtil.castToCent(amount));
			//自己的服务器IP地址
			data.put("spbill_create_ip", InetAddress.getLocalHost().getHostAddress());
			//异步通知地址（请注意必须是外网）
			data.put("notify_url", wxConfig.getNotifyUrl());
			//交易类型
			data.put("trade_type", tradeType);
			//附加数据，在查询API和支付通知中原样返回，该字段主要用于商户携带订单的自定义数据
			data.put("attach", "");
			data.put("sign", WXPayUtil.generateSignature(data, wxConfig.getKey(),
					WXPayConstants.SignType.MD5));
			//使用官方API请求预付订单
			Map<String, String> response = wxpay.unifiedOrder(data);
			if ("SUCCESS".equals(response.get("return_code"))) {//主要返回以下5个参数
				Map<String, String> param = new HashMap<>();
				param.put("appid", wxConfig.getAppID());
				param.put("partnerid", response.get("mch_id"));
				param.put("prepayid", response.get("prepay_id"));
				param.put("package", "Sign=WXPay");
				param.put("noncestr", WXPayUtil.generateNonceStr());
				param.put("timestamp", System.currentTimeMillis() / 1000 + "");
				param.put("sign", WXPayUtil.generateSignature(param, wxConfig.getKey(),
						WXPayConstants.SignType.MD5));
				return AjaxResult.success("成功",JSON.toJSONString(param));
			} else {
				return AjaxResult.success("失败",response.get("return_msg"));
			}
		} catch (Exception e) {
			e.printStackTrace();
			return AjaxResult.success("下单失败");
		}
	}

	/**
	 * 	支付宝支付
	 * @param orderNo
	 * @param amount
	 * @param remark
	 * @return
	 */
	private AjaxResult createAliPayOrder(String orderNo, String amount, String remark) {
		//构造client
		CertAlipayRequest certAlipayRequest = new CertAlipayRequest ();

		//设置网关地址
		certAlipayRequest.setServerUrl("https://openapi.alipay.com/gateway.do");
		//设置应用Id
		certAlipayRequest.setAppId(alipayConfig.getAppId());
		//设置应用私钥
		certAlipayRequest.setPrivateKey(alipayConfig.getAppPrivateKey());
		//设置请求格式，固定值json
		certAlipayRequest.setFormat("json");	
		//设置字符集
		certAlipayRequest.setCharset("UTF-8");
		//设置签名类型
		certAlipayRequest.setSignType("RSA2");
		//设置应用公钥证书路径
		certAlipayRequest.setCertPath(alipayConfig.getAppCertPublicKey());
		//设置支付宝公钥证书路径
		certAlipayRequest.setAlipayPublicCertPath(alipayConfig.getAlipayCertPublicKeyRSA2());
		//设置支付宝根证书路径
		certAlipayRequest.setRootCertPath(alipayConfig.getAlipayRootCert());
		//构造client
		AlipayClient alipayClient = null;
		try {
			alipayClient = new DefaultAlipayClient(certAlipayRequest);
		} catch (AlipayApiException e1) {
			e1.printStackTrace();
		}
		//SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
		AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
		model.setSubject(remark);
		model.setBody(remark);
		model.setOutTradeNo(orderNo);
		model.setTotalAmount(amount);
		model.setTimeoutExpress("1c");
		model.setProductCode("QUICK_MSECURITY_PAY");
		//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
		AlipayTradeAppPayRequest appPayRequest = new AlipayTradeAppPayRequest();
		appPayRequest.setBizModel(model);
		appPayRequest.setNotifyUrl(alipayConfig.getNotifyUrl());// 回调地址
		try {
			AlipayTradeAppPayResponse appPayResponse = alipayClient.sdkExecute(appPayRequest);
			return AjaxResult.success("成功",appPayResponse.getBody());	
		} catch (Exception e) {
			return AjaxResult.error(e.getMessage());
		}
	}
	
	@Override
	public AjaxResult getRewardConsultationOrder(RewardVO rewardVO, HttpServletRequest request) {
		Long loginUserId = getLoginUserId();
		if(null == loginUserId) {
			return AjaxResult.error(50010,"请重新登录");
		}
		try {
			// 查询当前用户VIP状态
			User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getId, loginUserId).select(User::getId,User::getVip));
			if(null == user) {
				return AjaxResult.error(50010,"请重新登录");
			}
			if(0 == user.getVip()) {
				rewardVO.setIsAnonymous(0);
			}
			OrderInfo orderInfo = new OrderInfo();
			orderInfo.setOrderType("3");
			//订单备注
			orderInfo.setRemark("打赏咨询师");
			// 订单号
			orderInfo.setOrderNo(OrderNumberGeneratorUtil.get());
			// 创建时间
			orderInfo.setCreateTime(new Date());
			// 支付用户ID
			orderInfo.setPayUserId(loginUserId);
			// 未支付
			orderInfo.setOrderStatus("0");
			// 订单时间
			orderInfo.setOrderCreateTime(new Date());
			// 订单支付类型
			orderInfo.setPayType(String.valueOf(rewardVO.getPayType()));
			//设置订单金额
			orderInfo.setOrderAmount(rewardVO.getAmount());
			//设置订单业务ID
			orderInfo.setRelatedId(0L);
			// 组装扩展信息
			ProblemConsult consult = new ProblemConsult();
			consult.setUserId(loginUserId);
			consult.setType(rewardVO.getType());
			consult.setDid(rewardVO.getDid());
			consult.setContent(rewardVO.getContent());
			consult.setAmount(rewardVO.getAmount());
			consult.setExtend(rewardVO.getBusinessId());
			consult.setIsAnonymous(rewardVO.getIsAnonymous());
			orderInfo.setExtend(JSONObject.toJSONString(consult));
			if(3 == rewardVO.getPayType()) { // 余额支付
				// 校验余额
				boolean checkUserAmount = userTotalCapitalService.checkUserAmount("3", loginUserId, rewardVO.getAmount());
				if(!checkUserAmount) {
					return AjaxResult.error("余额不足请先充值");
				}
				// 减少余额
				userTotalCapitalService.initUserTotalCapital("3", loginUserId, rewardVO.getAmount(), 0);
				// 已支付
				orderInfo.setOrderStatus("1");
				problemConsultMapper.insert(consult);
				orderInfo.setRelatedId(consult.getId());
				// 保存订单信息
				orderInfoMapper.insert(orderInfo);
				taskAsync.sendSystemMsg(orderInfo.getPayUserId(), 0l, 4, "", "");
				return AjaxResult.success("成功");
			}
			// 保存订单信息
			orderInfoMapper.insert(orderInfo);
			if("1".equals(orderInfo.getPayType())) {
				return createWxPayOrder(orderInfo.getOrderNo(), String.valueOf(rewardVO.getAmount()), orderInfo.getRemark(), "APP");
				
			}else if("2".equals(orderInfo.getPayType())) {
				return createAliPayOrder(orderInfo.getOrderNo(), String.valueOf(rewardVO.getAmount()), orderInfo.getRemark());
			}
			return AjaxResult.error("参数异常");
		} catch (Exception e) {
			e.printStackTrace();
			return AjaxResult.error("网络繁忙");
		}
	}
	
	@Override
	public AjaxResult getOrderGrabbingPool(Integer pageNo, Integer type,HttpServletRequest request) {
		Long loginUserId = getLoginUserId();
		if(null == loginUserId) {
			return AjaxResult.error(50010,"请重新登录");
		}
		try {
			//pageNo = (pageNo -1)*10;
			// 1=我的提问 2=所有提问
			if(2 == type) {
				loginUserId = null;
			}
			IPage<OrderGrabbingPoolDTO> orderGrabbingPool = problemConsultMapper.getOrderGrabbingPool(new Page<OrderGrabbingPoolDTO>().setCurrent(pageNo).setSize(10),null,loginUserId);
			orderGrabbingPool.getRecords().stream().forEach(pool ->{
				// 处理时间
				if(null != pool.getCreateTime()) {
					pool.setTime(DateUtils.getTimeCompareStringFootprint(pool.getCreateTime()));
				}
				// 是否匿名
				if(1 == pool.getIsAnonymous()) {
					pool.setNickName("匿名用户");
				}
			});
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("total", orderGrabbingPool.getTotal());
			map.put("list", orderGrabbingPool.getRecords());
			return AjaxResult.success(map);
		} catch (Exception e) {
			e.printStackTrace();
			return AjaxResult.error("网络繁忙");
		}
		
	}
	@Override
	public AjaxResult getAnswerDetail(Long id, HttpServletRequest request) {
		Long loginUserId = getLoginUserId();
		if(null == loginUserId) {
			return AjaxResult.error(50010,"请重新登录");
		}
		try {
			IPage<OrderGrabbingPoolDTO> list = problemConsultMapper.getOrderGrabbingPool(new Page<OrderGrabbingPoolDTO>().setCurrent(0).setSize(10),id,null);
			if(CollectionUtil.isEmpty(list.getRecords())) {
				return AjaxResult.error("咨询不存在");
			}
			OrderGrabbingPoolDTO orderGrabbingPool = list.getRecords().get(0);
			// 是否匿名
			if(1 == orderGrabbingPool.getIsAnonymous()) {
				orderGrabbingPool.setNickName("匿名用户");
			}
			if(null != orderGrabbingPool.getCreateTime()) {
				orderGrabbingPool.setTime(DateUtils.format(orderGrabbingPool.getCreateTime(), "yyyy/MM/dd HH:mm"));
			}
			// 占卜结果
			List<String> asList = Arrays.asList(orderGrabbingPool.getDid().split(","));
			List<SystemDivine> divineList = systemDivineMapper.selectList(new LambdaQueryWrapper<SystemDivine>().in(SystemDivine::getId, asList.stream().map(Long::valueOf).collect(Collectors.toList())));
			if(CollectionUtil.isNotEmpty(divineList)) {
				orderGrabbingPool.setDivineList(divineList);
			}
			// 解答列表
			List<AnswerDTO> answerList = problemAnswerMapper.getAnswerList(orderGrabbingPool.getId(),null);
			if(CollectionUtil.isNotEmpty(answerList)) {
				answerList.stream().forEach(answer ->{
					if(null != answer.getBirthday()) {
						//处理年龄
						if(answer.getBirthday() != null) {
							answer.setAge(CommonUtil.getAge(answer.getBirthday()));
						}else {
							answer.setAge(22);
						}
						// 处理语音
//						if(loginUserId.longValue() != orderGrabbingPool.getUserId().longValue() || loginUserId.longValue() != answer.getUserId().longValue()) {
//							answer.setVoice("");
//						}
					}
					// 处理打赏金额
					if(1 == answer.getIsAdopt()) {
						answer.setAmount(orderGrabbingPool.getAmount().stripTrailingZeros().toPlainString());
						if(null != answer.getUpdateTime()) {
							orderGrabbingPool.setCompleteTime(DateUtils.format(answer.getUpdateTime(), "yyyy/MM/dd HH:mm"));
						}
					}
				});
				orderGrabbingPool.setAnswerList(answerList);
			}
			return AjaxResult.success(orderGrabbingPool);
		} catch (Exception e) {
			e.printStackTrace();
			return AjaxResult.error("网络繁忙");
		}
		
	}
	@Override
	public AjaxResult replyProblem(AnswerDTO answer, HttpServletRequest request) {
		Long loginUserId = getLoginUserId();
		if(null == loginUserId) {
			return AjaxResult.error(50010,"请重新登录");
		}
		try {
			User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getId, loginUserId).select(User::getId,User::getUserType,User::getIsConsultantAuth));
			if(null == user) {
				return AjaxResult.error(50010,"请重新登录");
			}
			if(1 != user.getIsConsultantAuth()) {
				return AjaxResult.error("只有咨询师才可回复");
			}
			ProblemConsult consult = problemConsultMapper.selectOne(new LambdaQueryWrapper<ProblemConsult>().eq(ProblemConsult::getId, answer.getId()).eq(ProblemConsult::getIsDel, 0)
					.select(ProblemConsult::getId,ProblemConsult::getUserId,ProblemConsult::getAmount,ProblemConsult::getContent));
			if(null == consult) {
				return AjaxResult.error("当前咨询的问题不存在");
			}
			if(loginUserId.longValue() == consult.getUserId().longValue()) {
				return AjaxResult.error("自己不可回复自己的提问");
			}
			Integer count = problemAnswerMapper.selectCount(new LambdaQueryWrapper<ProblemAnswer>().eq(ProblemAnswer::getCid, answer.getId()));
			if(count >= 3) {
				return AjaxResult.error("只能有三位咨询师回复~");
			}
			Integer selectCount = problemAnswerMapper.selectCount(new LambdaQueryWrapper<ProblemAnswer>().eq(ProblemAnswer::getCid, answer.getId())
					.eq(ProblemAnswer::getUserId, loginUserId));
			if(selectCount > 0) {
				return AjaxResult.error("已回复不可重复回复");
			}
			ProblemAnswer p = new ProblemAnswer();
			p.setUserId(loginUserId);
			p.setCid(answer.getId());
			p.setVoice(answer.getVoice());
			p.setVoiceLength(answer.getVoiceLength());
			problemAnswerMapper.insert(p);
			if(0 == count) { // 第一次回答
				// 记录到定时任务表 ， 24小时过期自动采纳
				// 抽佣
				consult.setAmount(consult.getAmount().multiply(priceSettingService.qryScale("orderProportion",consult.getAmount())));
				taskAsync.addProblemAnswerTask(consult.getUserId(),loginUserId, consult.getAmount(), p.getId(),consult.getId());
			}
			// 用户问题被回答推送消息
			taskAsync.sendSystemMsg(consult.getUserId(), 0l, 5, String.valueOf(consult.getId()),"");
		} catch (Exception e) {
			e.printStackTrace();
			return AjaxResult.error("网络繁忙");
		}
		return AjaxResult.success();
	}
	@Override
	public AjaxResult adoptUserReply(Long id, HttpServletRequest request) {
		Long loginUserId = getLoginUserId();
		if(null == loginUserId) {
			return AjaxResult.error(50010,"请重新登录");
		}
		try {
			 ProblemAnswer answer = problemAnswerMapper.selectOne(new LambdaQueryWrapper<ProblemAnswer>().eq(ProblemAnswer::getId, id).select(ProblemAnswer::getId,
					ProblemAnswer::getIsAdopt,ProblemAnswer::getCid,ProblemAnswer::getUserId));
			if(null == answer) {
				return AjaxResult.error("该条回复不存在");
			}
			ProblemConsult consult = problemConsultMapper.selectOne(new LambdaQueryWrapper<ProblemConsult>().eq(ProblemConsult::getId, answer.getCid()).select(ProblemConsult::getId
					,ProblemConsult::getAmount,ProblemConsult::getUserId));
			if(null == consult) {
				return AjaxResult.error("问答不存在");
			}
			if(loginUserId.longValue() != consult.getUserId().longValue()) {
				return AjaxResult.error("不可采纳TA人问答");
			}
			Integer count = problemAnswerMapper.selectCount(new LambdaQueryWrapper<ProblemAnswer>().eq(ProblemAnswer::getCid, answer.getCid()).eq(ProblemAnswer::getIsAdopt, 1));
			if(count > 0) {
				return AjaxResult.error("当前问答已采纳咨询师回复");
			}
			answer.setIsAdopt(1);
			answer.setUpdateTime(new Date());
			problemAnswerMapper.updateById(answer);
			// 采纳了某个咨询师 进行打赏
			if(null != consult.getAmount()) {
				// 抽佣
				consult.setAmount(consult.getAmount().multiply(priceSettingService.qryScale("orderProportion",consult.getAmount())));
				userTotalCapitalService.initUserTotalCapital("1", answer.getUserId(), consult.getAmount(), 1);
				UserCapitalFlow userCapitalFlow = new UserCapitalFlow();
				userCapitalFlow.setType(4);
				userCapitalFlow.setBusinessType(3);
				userCapitalFlow.setAmount(consult.getAmount());
				userCapitalFlow.setUserId(answer.getUserId());
				userCapitalFlow.setToUserId(consult.getUserId());
				userCapitalFlow.setOrderNo(OrderNumberGeneratorUtil.get());
				userCapitalFlow.setRemark("回复用户问答被采纳");
				userCapitalFlow.setRelatedId(id);
				userCapitalFlowService.save(userCapitalFlow);
				// 发送自定义消息 用户名义发送给咨询师 
				//taskAsync.sendDivineOrderMsg(loginUserId, answer.getUserId(),consult.getId(),id);
				//taskAsync.addProblemAnswerMsg(loginUserId, answer.getUserId(), 1);
				taskAsync.sendSystemMsg(answer.getUserId(), 0l, 6, String.valueOf(consult.getId()), "");
				// 删除自动采纳定时任务
				List<OrderTask> list = orderTaskService.list(new LambdaQueryWrapper<OrderTask>().eq(OrderTask::getRelatedId, answer.getId()).eq(OrderTask::getStatus, 0));
				if(CollectionUtil.isNotEmpty(list)) {
					list.stream().forEach(task ->{
						task.setStatus(2);
						task.setUpdateTime(new Date());
						task.setRemark(task.getRemark()+"-用户已采纳,删除定时任务");
					});
					orderTaskService.updateBatchById(list);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			return AjaxResult.error("网络繁忙");
		}
		return AjaxResult.success();
	}
}
